package component;

import javax.media.j3d.Transform3D;
import javax.vecmath.Point3d;
import javax.vecmath.Vector3d;

import math.Precision;
import math.Spherical;
import node.IntersectionValidator;
import node.TubeNode;

public class Tube extends AbstractComponent {

	private final TubeNode tubeNode;
	
	private boolean hasPrimaryConnection;
	private boolean hasSecondaryConnection;
	
	public Tube(Point3d pos, double zRotation, double yRotation, IntersectionValidator validator) {
		super(validator);
		
		tubeNode = new TubeNode(this,pos, new Spherical(zRotation, yRotation), Status.NORMAL);
		this.setGeoNode(tubeNode);
	}
	
	public Point3d getSecondaryPosition() {
		return tubeNode.getSecondaryPosition();
	}
	
	public boolean isConnectedAtPrimary() {
		return hasPrimaryConnection;
	}
	
	public boolean isConnectedAtSecondary() {
		return hasSecondaryConnection;
	}
	
	
	public Point3d[] getFreeConnectionPositions() {
		if (isConnectedAtPrimary() && isConnectedAtSecondary())
			return new Point3d[0];
		if (isConnectedAtPrimary())
			return new Point3d[] {this.getSecondaryPosition()};
		if (isConnectedAtSecondary())
			return new Point3d[] {this.getPos()};
		
		return new Point3d[] {getPos(), getSecondaryPosition()};
	}
	
	@Deprecated
	@Override
	public void setRotation(double zRotation, double yRotation) {
		tubeNode.setRotation(zRotation, yRotation);
	}
	
	@Override
	public double getZOrientation() {
		return tubeNode.getZOrientation();
	}
	
	@Override
	public double getYOrientation() {
		return tubeNode.getYOrientation();
	}
	
	@Override
	public Spherical getOrientation() {
		return tubeNode.getOrientation();
	}
	
	@Override
	public void setOrientation(Spherical orientation) {
		tubeNode.setOrientation(orientation);
	}
	
	
	@Override
	public boolean canConnectTo(AbstractComponent other) {
		if (other instanceof Tube) return false;
		
		if (!hasPrimaryConnection && Precision.compare(this.getPos(), other.getPos()))
			return true;
		
		if (!hasSecondaryConnection && Precision.compare(this.getSecondaryPosition(), other.getPos()))
			return true;
		
		return false;
	}

	@Override
	public void componentsConnected(Connection connection) {
		Ball ball = connection.getBall();
		
		if (Precision.compare(ball.getPos(), this.getPos()))
			hasPrimaryConnection = true;
		else if (Precision.compare(ball.getPos(), this.getSecondaryPosition()))
			hasSecondaryConnection = true;
	}

	@Override
	public void componentsDisconnected(Connection connection) {
		Ball ball = connection.getBall();
		
		if (Precision.compare(ball.getPos(), this.getPos()))
			hasPrimaryConnection = false;
		else if (Precision.compare(ball.getPos(), this.getSecondaryPosition()))
			hasSecondaryConnection = false;
	}

	@Override
	public void applyTransform(Transform3D transform) {
		Point3d p1 = this.getPos();
		Point3d p2 = this.getSecondaryPosition();
		transform.transform(p1);
		transform.transform(p2);
		Vector3d newOrientation = new Vector3d();
		newOrientation.sub(p2,p1);
		
		Spherical orientation = new Spherical();
		orientation.setVector(newOrientation);
		
		this.setOrientation(orientation);
		this.setPos(p1);
	}

}
